class Action
  class NoActionFoundError < StandardError; end
  
  class << self
    def inherited(child)
      @@subclasses ||= []
      @@subclasses << child
      super
    end
  
    def run(args=[])
      action_name = args.shift
      action_classs = @@subclasses.detect{ |subclass| to_action_name(subclass) == action_name }
      raise NoActionFoundError.new("can not find action named #{action_name}, all action list is: #{action_names}") unless action_classs
      action_classs.new(TM).execute(*args)
    end
  
    def action_names
      @@subclasses.collect{ |subclass| to_action_name(subclass) }.join(', ')
    end
  
    def to_action_name(clazz)
      clazz.name.underscore
    end
  end
    
  def initialize(mate)
    @mate = mate
    @project = Project.new(mate.project_directory)
  end
end

class UpdateCodeIndexForWholeProject < Action
  def execute
    benchmark 'indexing whole project' do 
      @project.code_index.update
    end
  end
end

class EditProjectIgnores < Action
  def execute
    `mate #{@project.ignore_setting_file}`
  end
end

class GotoDeclaration < Action
  def execute
    locations = @project.code_index.locations_for(TM.current_word)
    return(TextMate.exit_show_tool_tip "No matches were found.") if locations.blank?
    menu_selector = lambda { |candidates| TextMate::UI.menu(candidates) rescue exit }
    LocationSelection.new(locations, menu_selector) do |selection|
      selection.selected.open if selection.selected
    end
  end
end

if $0 == __FILE__
  Action.run(ARGV)
end